package com.epalmpay.service.weixin.impl;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import com.alibaba.fastjson.JSONObject;
import com.epalmpay.entity.*;
import com.epalmpay.enumdef.ActivityEnum;
import com.epalmpay.mapper.*;
import com.epalmpay.service.bonus.IBonusService;
import com.epalmpay.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.epalmpay.dto.member.SubscribeMemberDTO;
import com.epalmpay.enumdef.BizEnum;
import com.epalmpay.enumdef.BizEnum.UserStatus;
import com.epalmpay.enumdef.CommonEnum;
import com.epalmpay.plugin.MyWxMpConfigStorage;
import com.epalmpay.service.activity.ICouponUserService;
import com.epalmpay.service.activity.IRedPackageUserService;
import com.epalmpay.service.weixin.IWxBaseService;
import com.epalmpay.util.DateUtil;
import com.epalmpay.util.Token;
import com.epalmpay.util.Tools;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import me.chanjar.weixin.mp.bean.result.WxMpUser;
import redis.clients.jedis.Jedis;


@Service("wxBaseService") 
public class WxBaseService implements IWxBaseService {
	
 private static final Logger logger = Logger.getLogger(WxBaseService.class);
	@Resource 
	private MemberMapper memberMapper;
	@Resource 
	private GroupWxconfigMapper groupWxconfigMapper;
	@Resource 
	private UserbaseMapper userbaseMapper;
	@Resource 
	private GroupMapper groupMapper;
	@Resource 
	private CrcodeMapper crcodeMapper;
	@Resource 
	private MemberGradeMapper memberGradeMapper;
	@Resource 
	private ShopMapper shopMapper;
	@Resource 
	private AgentMapper agentMapper;

	@Resource
	ActivityRoutineMapper activityRoutineMapper;
	@Resource
	ActivityBaseMapper activityBaseMapper;
	@Resource
	ActivityRoutineRuleMapper activityRoutineRuleMapper;
	@Resource
	IRedPackageUserService redPackageUserService;
	@Resource
	ICouponUserService couponUserService;
	@Resource
	IBonusService bonusService;
	
	
//	private EmojiConverter emojiConverter = EmojiConverter.getInstance();
	
	
	@Override
	public SubscribeMemberDTO savesubscribe(String developid,String eventKey, WxMpUser wxMpUser,String nickname) throws Exception {
		//根据原始ID查询微信配置
		GroupWxconfig groupWxconfig=groupWxconfigMapper.selectByTxidKey(developid);
		SubscribeMemberDTO subscribeMember=new SubscribeMemberDTO();
		Crcode crcode=null;
		if(groupWxconfig!=null){
			 //根据openId查询会员详情
			Member member=memberMapper.selectOpenId(wxMpUser.getOpenId(),groupWxconfig.getGroupId());
			Date date=new Date();
			Member memberInfo=new Member();
			Group group=groupMapper.selectByPrimaryKey(groupWxconfig.getGroupId());
			subscribeMember.setMerchantName(group.getMerchantName()); 
			  if(member==null){
						    	  Userbase userbase=new Userbase();
								  userbase.setGroupId(groupWxconfig.getGroupId());
								  userbase.setUserType(CommonEnum.UserType.User.getType());
								  userbase.setBz("会员关注微信");
								  userbase.setGmtCreate(date);
								  userbase.setGmtModified(date);
								  userbase.setStatus(UserStatus.Normal.getType());
								  userbaseMapper.insertKey(userbase);
								String CertNo="000000000000000000";//长度必须是18位
								String MobilePhone="00000000000";
								memberInfo.setAddress(null);
								memberInfo.setBirthday(null);
								memberInfo.setCardNo(DateUtil.getMonth()+Tools.getRandomNum(6));//会员卡号
							if(Tools.isEmpty(eventKey)){
									  //微信二维码场景id为空标示普通扫码关注
									  memberInfo.setFromType(BizEnum.MemberDevelopeFrom.SelfRegister.getType());//发展来源(枚举)
									  memberInfo.setFromId(group.getId());   //发展来源id 门店id 大商户id  会员id
									  memberInfo.setFromName(BizEnum.MemberDevelopeFrom.SelfRegister.getName());//发展来源名称
									  memberInfo.setFromMode(BizEnum.MemberDevelopeMode.ScanQRcode.getType());//发展方式(枚举) 
								  }else{
									  //根据场景id查询关注类型
									  crcode=crcodeMapper.selectBySceneId(Integer.parseInt(eventKey));
									  memberInfo=getmemberInfo(memberInfo, eventKey, crcode,group.getId(),subscribeMember);
						      }
									  memberInfo.setGmtCreate(new Date());
									  memberInfo.setGmtModified(null);
								//	  MemberGrade memberGrade=memberGradeMapper.selectMemberGradeByGroupIdAndGradeName(group.getId(), BizEnum.MemberGradeDefault.attention.getName());
									  
									  //取值第一个会员等级id
									  List<MemberGrade> memberGradeList=memberGradeMapper.selectGroupList(group.getId());
									  
									  if(memberGradeList.size()>0){ 
										  memberInfo.setGradeId(memberGradeList.get(0).getId());//会员等级
									  }else{
										  memberInfo.setGradeId(1L);//会员等级
									  }
									  memberInfo.setGroupId(groupWxconfig.getGroupId());
									  memberInfo.setIdNo(CertNo);//身份证号
									  memberInfo.setName(nickname);
									  memberInfo.setOpenid(wxMpUser.getOpenId());
									  memberInfo.setPhone(MobilePhone);
									  memberInfo.setPicture(wxMpUser.getHeadImgUrl());//图片
									  memberInfo.setSex(wxMpUser.getSexId()%2);
									  memberInfo.setStatus(1);//会员状态(枚举)
									  memberInfo.setTradePassword(null);//交易密码
									  memberInfo.setUserId(userbase.getId());
									  memberInfo.setVirtualCard(null);//虚拟卡号 对应支付平台userId
									  memberInfo.setWalletGmtCreate(new Date());
									  memberInfo.setWalletStatus(0);//钱包状态(0:未开;1:开通)
									  memberInfo.setWeixinName(nickname);
									  memberInfo.setWxsubStaus(BizEnum.WebChatConcernStatus.Concerned.getType());
									  memberInfo.setConcernTime(date);
									  memberInfo.setLastTradeTime(null);
									  memberInfo.setPerfectTime(null);
									  memberInfo.setUnconcernMemberNum(null);
									  memberInfo.setBalance(null); 
									  memberInfo.setApproveStatus(0);//默认未认证
									  memberInfo.setUpdateTime(date);
									  memberInfo.setBonusAmount(0);
									  memberInfo.setBonusFreeze(0); 
									  memberInfo.setBonusLocked(0);
									  memberInfo.setBonusPreAcount(0);
									  memberMapper.insertSelective(memberInfo);
									  System.out.println("会员编号："+memberInfo.getId());
									  //立即赠送优惠券、积分、红包
								  List<ActivityRoutine> activityRoutineList = activityRoutineMapper.selectByActivityType(ActivityEnum.RoutineActivityType.UpdateSend.getType());
								  for(ActivityRoutine activityRoutine:activityRoutineList) {
									  ActivityBase activityBase = activityBaseMapper.selectByRoutineId(activityRoutine.getActivityId());
									  if(activityBase.getGroupId() == group.getId()) {

									  		logger.info("活动规则id="+activityRoutine.getActivityId());
										  //全部会员
										  if(activityRoutine.getMemberRiented() == ActivityEnum.MemberOriented.AllMember.getType()) {
											  List<ActivityRoutineRule> activityRoutineRuleList = activityRoutineRuleMapper.selectValidRuleListByActivityId(activityRoutine.getActivityId());
											  for (ActivityRoutineRule activityRoutineRule : activityRoutineRuleList) {
												  if (activityRoutineRule.getSendType() == null)
													  activityRoutineRule.setSendType(ActivityEnum.ActivitySendType.NoSend.getType());

												  switch (ActivityEnum.ActivitySendType.fromType(activityRoutineRule.getSendType())) {
													  case RedPackage:
														  try {
															  redPackageUserService.sendOneMemberRedPackage(memberInfo.getId(),
																	  activityRoutineRule.getRedpackageId(), activityBase.getId(), ActivityEnum.RedPackageGetType.ActivitySend.getType(), null);
														  } catch ( Exception ae ) {
															  ae.printStackTrace();
															  logger.error(ae);
														  }
														  break;
													  case Coupon:
														  try {
															  couponUserService.sendOneMemberCoupon(memberInfo.getId(),
																	  activityRoutineRule.getCouponId(), activityBase.getId(), ActivityEnum.RedPackageGetType.ActivitySend.getType(), null);
														  } catch ( Exception ae ) {
															  ae.printStackTrace();
															  logger.error(ae);
														  }
														  break;
													  case Bonus:
														  try {
//如果升级活动面对所有会员，和对应等级会员规则。
															  if (activityRoutine.getMemberRiented() == ActivityEnum.MemberOriented.AllMember.getType()) {
																  if (activityRoutineRule.getMemberGrade() == null) {
																	  BonusSendLog bonusSendLog = BonusSendLog.build(activityBase.getGroupId(), memberInfo.getId(), ActivityEnum.BonusSendType.UpdateSend.getType(),
																			  activityRoutineRule.getIntegral(), ActivityEnum.BonusSendStatus.Accounted.getType(), null, null, null, "会员升级送", activityBase.getId());
																	  bonusService.sendOneMemberBonus(bonusSendLog);
																  }
															  } else if (memberInfo.getGradeId().equals(activityRoutineRule.getMemberGrade())) {
																  BonusSendLog bonusSendLog = BonusSendLog.build(activityBase.getGroupId(), memberInfo.getId(), ActivityEnum.BonusSendType.UpdateSend.getType(),
																		  activityRoutineRule.getIntegral(), ActivityEnum.BonusSendStatus.Accounted.getType(), null, null, null, "会员升级送", activityBase.getId());
																  bonusService.sendOneMemberBonus(bonusSendLog);
															  }

														  } catch ( Exception e ) {
															  e.printStackTrace();
															  logger.error(e);
														  }
														  break;
													  default:
														  break;
												  }


											  }
											  //按会员等级
										  }else{
											  List<ActivityRoutineRule> activityRoutineRuleList = activityRoutineRuleMapper.selectValidRuleListByActivityId(activityRoutine.getActivityId());
                                              for (ActivityRoutineRule activityRoutineRule : activityRoutineRuleList) {
                                                  if (memberGradeList.get(0).getId()==activityRoutineRule.getMemberGrade()) {
                                                      if (activityRoutineRule.getSendType() == null)
                                                          activityRoutineRule.setSendType(ActivityEnum.ActivitySendType.NoSend.getType());

                                                      switch (ActivityEnum.ActivitySendType.fromType(activityRoutineRule.getSendType())) {
                                                          case RedPackage:
                                                              try {
                                                                  redPackageUserService.sendOneMemberRedPackage(memberInfo.getId(),
                                                                          activityRoutineRule.getRedpackageId(), activityBase.getId(), ActivityEnum.RedPackageGetType.ActivitySend.getType(), null);
                                                              } catch ( Exception ae ) {
                                                                  ae.printStackTrace();
                                                                  logger.error(ae);
                                                              }
                                                              break;
                                                          case Coupon:
                                                              try {
                                                                  couponUserService.sendOneMemberCoupon(memberInfo.getId(),
                                                                          activityRoutineRule.getCouponId(), activityBase.getId(), ActivityEnum.RedPackageGetType.ActivitySend.getType(), null);
                                                              } catch ( Exception ae ) {
                                                                  ae.printStackTrace();
                                                                  logger.error(ae);
                                                              }
                                                              break;
                                                          case Bonus:
                                                              try {
//如果升级活动面对所有会员，和对应等级会员规则。
                                                                  if (activityRoutine.getMemberRiented() == ActivityEnum.MemberOriented.AllMember.getType()) {
                                                                      if (activityRoutineRule.getMemberGrade() == null) {
                                                                          BonusSendLog bonusSendLog = BonusSendLog.build(activityBase.getGroupId(), memberInfo.getId(), ActivityEnum.BonusSendType.UpdateSend.getType(),
                                                                                  activityRoutineRule.getIntegral(), ActivityEnum.BonusSendStatus.Accounted.getType(), null, null, null, "会员升级送", activityBase.getId());
                                                                          bonusService.sendOneMemberBonus(bonusSendLog);
                                                                      }
                                                                  } else if (memberInfo.getGradeId().equals(activityRoutineRule.getMemberGrade())) {
                                                                      BonusSendLog bonusSendLog = BonusSendLog.build(activityBase.getGroupId(), memberInfo.getId(), ActivityEnum.BonusSendType.UpdateSend.getType(),
                                                                              activityRoutineRule.getIntegral(), ActivityEnum.BonusSendStatus.Accounted.getType(), null, null, null, "会员升级送", activityBase.getId());
                                                                      bonusService.sendOneMemberBonus(bonusSendLog);
                                                                  }

                                                              } catch ( Exception e ) {
                                                                  e.printStackTrace();
                                                                  logger.error(e);
                                                              }
                                                              break;
                                                          default:
                                                              break;
                                                      }
                                                  }
                                              }

										  }
									  }
								  }
							  subscribeMember.setType(crcode!=null?crcode.getType():BizEnum.ScancrcodeType.subscribe.getType());
						      subscribeMember.setGroupId(group.getId());
							  subscribeMember.setMemberId(memberInfo.getId());
				  System.out.println("会员编号1："+subscribeMember.getMemberId());
							  return subscribeMember;
						      
				  }else{
					      if(member.getWalletStatus()==1){
					    	  subscribeMember.setFlag(true);
					      }
						  member.setWxsubStaus(BizEnum.WebChatConcernStatus.Concerned.getType());
						  member.setPicture(wxMpUser.getHeadImgUrl());//图片
						  member.setWeixinName(nickname);
						  member.setSex(wxMpUser.getSexId()%2);
						  member.setConcernTime(date);
						  member.setUnconcernTime(date); 
						  member.setUpdateTime(date);
						  memberMapper.updateByPrimaryKeySelective(member);
						  if(Tools.notEmpty(eventKey)){
							  crcode=crcodeMapper.selectBySceneId(Integer.parseInt(eventKey));
							  subscribeMember.setType(crcode!=null?crcode.getType():BizEnum.ScancrcodeType.subscribe.getType());
						  }else{
							  subscribeMember.setType(BizEnum.ScancrcodeType.subscribe.getType());//普通关注
						  }
						  subscribeMember.setGroupId(member.getGroupId());
						  subscribeMember.setMemberId(member.getId()); 
						  return subscribeMember;
				  }
		 }
		 return subscribeMember;
	}
	
	
	
	
	public  Member  getmemberInfo(Member memberInfo,String eventKey,Crcode crcode,Long groupId,SubscribeMemberDTO subscribeMember){
		  if(crcode!=null){
			  switch (crcode.getType()) {
				case 2:   //1用户自主注册 渠道发展 2表示代理商 3表示门店 4表示会员用户推广 5表示钱包二维码   6门店pos机发展
					memberInfo.setFromType(BizEnum.MemberDevelopeFrom.AgentDevelope.getType());
					Agent agent=agentMapper.selectUserId(crcode.getUserId());
					if(agent!=null){
						memberInfo.setFromId(agent.getId());  
						memberInfo.setFromName(agent.getMerchantName());
						memberInfo.setFromMode(BizEnum.MemberDevelopeMode.ScanQRcode.getType());//发展方式(枚举) 
						
						//会员发展会员 赠送优惠券红包等信息
						subscribeMember.setSourceId(agent.getId()); 
					}
					break;
				case 3:
					memberInfo.setFromType(BizEnum.MemberDevelopeFrom.ShopDevelope.getType());
					Shop shop=shopMapper.selectUserId(crcode.getUserId());  
					if(shop!=null){
						memberInfo.setFromId(shop.getId());   
						memberInfo.setFromName(shop.getMerchantName());
						memberInfo.setFromMode(BizEnum.MemberDevelopeMode.ScanQRcode.getType());//发展方式(枚举) 
						
						//会员发展会员 赠送优惠券红包等信息
						subscribeMember.setSourceId(shop.getId()); 
					}
					break;
				case 4:
					memberInfo.setFromType(BizEnum.MemberDevelopeFrom.UserDevelope.getType());
					Member memberUser=memberMapper.selectByPrimaryUserId(crcode.getUserId());
					if(memberUser!=null){
						memberInfo.setFromId(memberUser.getId());   
						memberInfo.setFromName(memberUser.getName());
						memberInfo.setFromMode(BizEnum.MemberDevelopeMode.ScanQRcode.getType());//发展方式(枚举) 
						
						//会员发展会员 赠送优惠券红包等信息
						subscribeMember.setSourceId(memberUser.getId()); 
					}
					break;	
				case 6:
					memberInfo.setFromType(BizEnum.MemberDevelopeFrom.ShopDevelope.getType());
					Shop shopPost=shopMapper.selectUserId(crcode.getUserId());  
					if(shopPost!=null){
						memberInfo.setFromId(shopPost.getId());   
						memberInfo.setFromName(shopPost.getMerchantName());
						memberInfo.setFromMode(BizEnum.MemberDevelopeMode.PosConsume.getType());//发展方式(枚举) 
						//门店post机发展
						subscribeMember.setSourceId(shopPost.getId());
					}
					break;	
				default:
					break;
				 }
			//更新扫码次数
			  crcode.setScanTimes(crcode.getScanTimes()==null?0:crcode.getScanTimes()+1); 
			  crcodeMapper.updateByPrimaryKey(crcode);
			}else{
			   memberInfo.setFromType(BizEnum.MemberDevelopeFrom.SelfRegister.getType());//发展来源(枚举)
		       memberInfo.setFromId(groupId);   //发展来源id 门店id 大商户id  会员id
		       memberInfo.setFromName(BizEnum.MemberDevelopeFrom.SelfRegister.getName());//发展来源名称 
		     }
		return memberInfo;
	}
	
	


	@Override
	public Boolean updateUnsubscribe(String openId,String developid) throws Exception {
		 //根据openId查询会员详情
		GroupWxconfig groupWxconfig=groupWxconfigMapper.selectByTxidKey(developid);
		 Member member=memberMapper.selectOpenId(openId,groupWxconfig.getGroupId());
		 if(member!=null){
			 member.setWxsubStaus(BizEnum.WebChatConcernStatus.UnConcern.getType());
			 member.setUnconcernTime(new Date()); 
			 member.setUpdateTime(new Date());
			 memberMapper.updateByPrimaryKeySelective(member);
		 }
		return true;
	}

	  private static final long DURATION = 6000L;
      LoadingCache<Long, MyWxMpConfigStorage> tokenCache = CacheBuilder.newBuilder().maximumSize(100)
            .expireAfterWrite(DURATION, TimeUnit.SECONDS).build(new CacheLoader<Long, MyWxMpConfigStorage>() {
                @Override
                public MyWxMpConfigStorage load(Long groupId) throws Exception {
                	//从redis中获取token
					RedisUtil redisUtil = new RedisUtil();
					Jedis jedis = redisUtil.getJedis();

                    logger.info("缓存未命中，重新请求Token");
                    MyWxMpConfigStorage wxConfigBean=new MyWxMpConfigStorage();         
                    GroupWxconfig groupWxconfig =groupWxconfigMapper.selectByGroupId(groupId);
                    String aesKey= groupWxconfig.getAeskey();
                    String token= groupWxconfig.getAccessToken();
                    if(StringUtils.isNotBlank(aesKey)){
                    	wxConfigBean.setAesKey(aesKey);
                    }else{
                    	wxConfigBean.setAesKey("vweAnCNuNxGo64BSLCvaCBp9vWzeYDaX1MRH9g6MqMQ");
                    }
                    if(StringUtils.isNotBlank(token)){
                    	wxConfigBean.setToken(token);
                    }else{
                    	wxConfigBean.setToken("zhousaijie123"); 
                    }
                    wxConfigBean.setAppId(groupWxconfig.getWxAppid());
                    wxConfigBean.setSecret(groupWxconfig.getWxAppsercet());  
                    wxConfigBean.setWxNotifyUrl(groupWxconfig.getWqNotifyurl());
					String jo = JSONObject.toJSONString(wxConfigBean);
					jedis.setex(groupId+"", (int)DURATION, jo);
					jedis.quit();
                    return wxConfigBean;
                }
          });


      /**
       * 获取缓存的大商户的微信信息
       * @return
       */
      public  MyWxMpConfigStorage getTokenByGroupId(Long groupId) {
          try {
          	//从redis中获取access_token
			  RedisUtil redisUtil = new RedisUtil();
			  Jedis jedis = redisUtil.getJedis();
			  String jedis_token = jedis.get(groupId+"");
			  MyWxMpConfigStorage access_token = new MyWxMpConfigStorage();
			  if(jedis_token != null) {//如果存在token
				  JSONObject jo = JSONObject.parseObject(jedis_token);

				  access_token.setToken(jo.getString("token"));
				  access_token.setAesKey(jo.getString("aesKey"));
				  access_token.setAppId(jo.getString("appId"));
				  access_token.setSecret(jo.getString("secret"));
				  access_token.setWxNotifyUrl(jo.getString("wxNotifyUrl"));
				  access_token.setAccessToken(jo.getString("token"));
			  } else {//如果不存在token
				  GroupWxconfig groupWxconfig =groupWxconfigMapper.selectByGroupId(groupId);
				  String aesKey= groupWxconfig.getAeskey();
				  String token= groupWxconfig.getAccessToken();
				  if(StringUtils.isNotBlank(aesKey)){
					  access_token.setAesKey(aesKey);
				  }else{
					  access_token.setAesKey("vweAnCNuNxGo64BSLCvaCBp9vWzeYDaX1MRH9g6MqMQ");
				  }
				  if(StringUtils.isNotBlank(token)){
					  access_token.setToken(token);
				  }else{
					  access_token.setToken("zhousaijie123");
				  }
				  access_token.setAppId(groupWxconfig.getWxAppid());
				  access_token.setSecret(groupWxconfig.getWxAppsercet());
				  access_token.setWxNotifyUrl(groupWxconfig.getWqNotifyurl());
				  jedis.setex(groupId+"", 7000, JSONObject.toJSONString(access_token));
			  }
			  jedis.quit();

        	  //MyWxMpConfigStorage access_token = tokenCache.get(groupId);
              logger.info("******************************************************************商户编号:" + groupId);
              logger.info("获取access_token:"+access_token.getAccessToken());
              logger.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
              return access_token;
          } catch (Exception e) {
              e.printStackTrace();
          }
          return null;
      }
      
      
	      LoadingCache<String, Token> gettoken = CacheBuilder.newBuilder().maximumSize(1000)
	              .expireAfterWrite(10L, TimeUnit.SECONDS).build(new CacheLoader<String, Token>() {
	                  @Override
	                  public Token load(String memberId) throws Exception {
	                	  System.out.println("-------------------------------------------会员缓存加载中-----------------------------");
	                      Token token=new Token();    
	                      token.setKey(memberId);   
	                      token.setValue(Tools.getRandomNum(6));
	                      return token;
	                  }
	            });
	        public   Boolean getToken(String memberId,String token) {
	            try {
	            	Token access_token = gettoken.get(memberId);
	            	if(access_token.getValue().equals(token)){
	            		 return true;
	            	  }
	                return false;
	            } catch (ExecutionException e) {
	                e.printStackTrace();
	            }
	            return false;
	        }
	        
	        
			@Override
			public void refresh(String memberId) {
				gettoken.refresh(memberId);
			}
	      
			@Override
			public void invalidate(String memberId) {
				gettoken.invalidate(memberId);
			}

			@Override
			public Token getToken(String memberId) {
				try {
					Token access_token = gettoken.get(memberId);
					return access_token;
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
				return null;
			}
      
      
      
}
